#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"

using namespace std;

// #define NUM 3

// int* p=nullptr;

// struct threadData
// {
//     string threadName;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[128];
//     snprintf(buffer, sizeof(buffer), "0x%x", tid);
//     return buffer;
// }

// void InitThreadData(threadData *td, int number)
// {
//     td->threadName = "thread-" + to_string(number);
// }

// void *threadRoutine(void *args)
// {
//     int test_i=0;
//     threadData *td = static_cast<threadData *>(args);
//     if(td->threadName=="thread-2") p=&test_i;
//     int i = 0;
//     while (i < 10)
//     {
//         cout << "pid: " << getpid() << ", tid: "
//              << toHex(pthread_self()) << ", threadname: " << td->threadName
//              << ",test_i: "<<test_i<<",&test_i: "<<&test_i<<endl;
//         sleep(1);
//         i++,test_i++;
//     }
//     delete td;
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for (int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;
//         threadData *td = new threadData;
//         pthread_create(&tid, nullptr, threadRoutine, td);
//         InitThreadData(td, i);
//         tids.push_back(tid);
//         //sleep(1);
//     }

//     sleep(1);
//     cout<<"main get a thread local value,val: "<<*p<<",&val: "<<p<<endl;

//     for (int i = 0; i < tids.size(); i++)
//     {
//         pthread_join(tids[i], nullptr);
//     }
//     return 0;
// }

// 同步与互斥
#define NUM 4

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class threadData
{
public:
    threadData(int number /*,pthread_mutex_t* mutex*/)
    {
        threadname = "thread-" + to_string(number);
        // lock=mutex;
    }

public:
    string threadname;
    // pthread_mutex_t* lock;
};

int tickets = 1000; // 用多线程，模拟一轮抢票

// void *getTicket(void *args)
// {
//     threadData *td = static_cast<threadData *>(args);
//     const char *name = td->threadname.c_str();
//     while (true)
//     {
//         //pthread_mutex_lock(td->lock);//申请锁成功，才能往后执行；不成功，阻塞等待。
//         pthread_mutex_lock(&lock);//申请锁成功，才能往后执行；不成功，阻塞等待。
//         if (tickets > 0)
//         {
//             usleep(1000);
//             printf("who=%s, get a ticket: %d\n", name, tickets); // ?
//             tickets--;
//             //pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);

//         }
//         else{
//             //pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);
//             break;
//         }
//         usleep(13);
//     }
//     printf("%s ... quit\n", name);
//     return nullptr;
// }

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        //此花括号表示这部分代码是临界区，并在括号内部自动完成了加锁解锁
        {
            LockGuard lockguard(&lock); // 临时的LockGuard对象  RAII风格的锁
            if (tickets > 0)
            {
                usleep(1000);
                printf("who=%s, get a ticket: %d\n", name, tickets); // ?
                tickets--;
            }
            else
                break;
        }
        usleep(13);
    }
    printf("%s ... quit\n", name);
    return nullptr;
}
int main()
{
    // pthread_mutex_t lock;
    // pthread_mutex_init(&lock,nullptr);

    vector<pthread_t> tids;
    vector<threadData *> thread_datas;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData(i /*,&lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }

    for (auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }

    for (auto td : thread_datas)
    {
        delete td;
    }

    // pthread_mutex_destroy(&lock);

    // pthread_exit(nullptr);
    return 0;
}